
package org.freez4.spring.bean.definition;

import org.freez4.spring.bean.factory.DefaultUserFactory;
import org.freez4.spring.bean.factory.UserFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * <pre>
 * Bean 初始化 Demo
 * 1. 基于@PostConstruct与@PreDestroy注解
 * 2. InitializingBean和DisposableBean API接口
 * 3. GenericBeanDefinition 自定义初始化方法和自定义销毁方法
 *
 * 初始化
 * 1. @PostConstruct
 * 2. InitializingBean#afterPropertiesSet()
 * 3. 自定义初始化方法 initUserFactory()
 * 销毁
 * 1. @PreDestroy
 * 2. DisposableBean#destroy()
 * 3. 自定义销毁方法 doDestroy()
 * 总结: 注解方式最先被执行，其次{@link InitializingBean#afterPropertiesSet()}, {@link DisposableBean#destroy()}，最后{@link GenericBeanDefinition#initMethodName}和{@link GenericBeanDefinition#destroyMethodName}。
 * </pre>
 *
 * @author youyongkun
 * @date 2021/7/1 14:15
 */
@Configuration
public class BeanInitializationDemo {

    private static final Logger logger = Logger.getLogger(BeanInitializationDemo.class.getName());

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class（配置类）
        applicationContext.register(BeanInitializationDemo.class);
        // 启动 Spring 应用上下文
        applicationContext.refresh();
        // 非延迟初始化在 Spring 应用上下文启动完成后，被初始化
        logger.log(Level.INFO, () -> "Spring 应用上下文已启动...");
        // 依赖查找 UserFactory
        UserFactory userFactory = applicationContext.getBean(UserFactory.class);
        logger.log(Level.INFO, userFactory::toString);
        logger.log(Level.INFO, () -> "Spring 应用上下文准备关闭...");
        // 关闭 Spring 应用上下文
        applicationContext.close();
        logger.log(Level.INFO, () -> "Spring 应用上下文已关闭...");
    }

    /**
     * 自定义初始化和销毁方法。
     *
     * @return DefaultUserFactory
     * @author 阿坤同学
     * @date 2023/12/6 5:17 PM
     */
    @Bean(initMethod = "initUserFactory", destroyMethod = "doDestroy")
    @Lazy(value = false)
    public DefaultUserFactory userFactory() {
        return new DefaultUserFactory();
    }
}
